<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="jspdf.umd.js"></script>
    <script src="html2canvas.min.js"></script>
</head>
<body>
    <img src="1.png" id="img" style="visibility: hidden;"/>
</body>
</html>
<script type="module">
    const {jsPDF} =jspdf;
    const doc = new jsPDF({unit:"pt",format:"a4"});    
    const pageWidth=595.28,pageHeight=841.89;
    const margin=[50,50,50,50];//上右下左
    const leftStartPos=margin[3];//左侧开始位置
    const rightEndPos=pageWidth-margin[1];//右侧结束位置   
    let currentpage=1;//当前页
    let globalEndYPos=margin[0];
    doc.addFont('simsun.ttf', 'simsun', 'normal');
    doc.setFont("simsun");
    doc.setPage(currentpage);
    //px转pt
    function pxTopt(num,unit){
        let val=num*0.5625;//num*0.75*0.75
        return unit?val+'pt':val
    }
    //pt校准
    function pt(num,unit){
        let val=num*0.75;
        return unit?val+'pt':val;
    }
    //是不是中文字符
    function cn(str){
        return /^[\u4e00-\u9fa5]+$/.test(str)
    }
        
    //计算字符宽度
    const textWidthContext=document.createElement("canvas").getContext('2d');
    function getTextWidth(text, font) {
        textWidthContext.font = font || `${doc.getFontSize()}pt simsun`;
        return textWidthContext.measureText(text).width;
    }
    //写入单行文本
    function addTextLine(text,opts={}){
        if(!opts.x)opts.x=margin[3];//默认以页面左边距为行超始横坐标
        if(!opts.y)opts.y=globalEndYPos;//默认以页面上边距为文字块起始纵坐标
        if(!opts.align)opts.align='left';//默认左对齐
        if(opts.fontSize)doc.setFontSize(opts.fontSize);
        if(opts.lineHeight)doc.setLineHeightFactor(opts.lineHeight);
        let maxWidth=pageWidth-margin[1]-margin[3];
        let width=getTextWidth(text);
        if(opts.align=="center" || opts.align=="right"){
            if(width>maxWidth){
                opts.x=margin[3];
            }else{
                if(opts.align=="center"){
                    opts.x=(pageWidth-width)/2
                }else{
                    opts.x=pageWidth-width-margin[1];
                }
            }
        }
        opts.align='left';
        doc.setTextColor(opts.color || '#333333');//默认颜色为#333333
        doc.text(text,opts.x,opts.y,opts);//写入文本
        globalEndYPos=opts.y+doc.getLineHeight();
    }

    //写入文本并返回文本范围
    function addText(text,opts={}){
        if(!opts.x)opts.x=margin[3];//默认以页面左边距为行超始横坐标
        if(!opts.y)opts.y=globalEndYPos;//默认以页面上边距为文字块起始纵坐标
        if(!opts.width)opts.width=pageWidth-margin[1]-margin[3];//最大宽度，默认以最大正文内容为行宽  
        if(!opts.align)opts.align='left';//默认左对齐
        if(opts.fontSize)doc.setFontSize(opts.fontSize);
        if(opts.lineHeight)doc.setLineHeightFactor(opts.lineHeight);
        doc.setTextColor(opts.color || '#333333');//默认颜色为#333333

        let res=doc.splitTextToSize(text,opts.width);//生成断行以后的数据
        let endYPos=opts.y;//初始纵坐标
        let lineHeight=doc.getLineHeight();//获取行高
        for(let i=0;i<res.length;i++){
            doc.text(res[i],opts.x,endYPos,opts);//写入文本
            //判断是否超过了一页中最大Y值，超过则新建页面，并将纵坐标设为页面开始位置，否则纵坐标增加一行距高度，以备下一行文字写入
            if(endYPos+lineHeight>pageHeight-margin[2]){
                doc.addPage();                
                doc.setPage(doc.getNumberOfPages());
                endYPos=margin[0];
            }else{
                endYPos+=lineHeight;
            }
        }
        globalEndYPos=endYPos;//设置当前页面纵坐标所在位置（全局）
        return Object.assign(opts,{            
            height:res.length*lineHeight,//整个文本块总高度
            lastLineXCOORD:getTextWidth(res[res.length-1])+opts.x,//最后一行字符总宽度
            endYPos//当前页面纵坐标所在位置
        });
    }
    //写入图片
    function addImg(imageData,opts={}){
        if(!opts.x)opts.x=margin[3];//默认以页面左边距为横坐标
        if(!opts.y)opts.y=globalEndYPos;//默认以页面上边距为纵坐标 
        opts.w=pt(opts.w || 100);
        opts.h=pt(opts.h || 100);
        opts.imageData=imageData;
        opts.compression="NONE";
        let maxHeight=pageHeight-margin[0]-margin[2]-globalEndYPos;
        let maxWidth=pageWidth-margin[1]-margin[3];
        if(opts.align=="center" || opts.align=="right"){
            if(opts.w>maxWidth){
                opts.x=margin[3];
            }else{
                if(opts.align=="center"){
                    opts.x=(pageWidth-opts.w)/2
                }else{
                    opts.x=pageWidth-opts.w-margin[1];
                }
            }
        }
        //图片超出当前页面
        if(maxHeight<opts.height){
            opts.y=margin[0];
            doc.addPage();                
            doc.setPage(doc.getNumberOfPages());            
        }
        doc.addImage(opts);
        globalEndYPos=opts.y+opts.height;
    }

    doc.setFontSize(pt(16));
    addTextLine("当前页面纵坐标所在位置",{fontSize:20,align:"center"})
    addText(new Array(1).fill("中文fdafd5eeee中文").join(""),{fontSize:9,y:globalEndYPos+doc.getLineHeight()});
    addImg(img,{w:100,h:150,format:'PNG',align:'center'});
    window.doc=doc;
    doc.save("a4.pdf");


    //let abc=doc.splitTextToSize(new Array(50).fill("中文fdafd5eeee中文").join(""),495);
    //console.log(abc);
    //doc.text(new Array(50).fill("中文fdafd5eeee中文").join(""),50,50,{maxWidth:495})
    //doc.text("595",595,50);
    // addText(new Array(400).fill("中文fdafd5eeee中文").join(""),{
    //     x:0,
    //     y:margin[0]
    // })
    //表格
    // doc.table(50,50,[
    //     {a:"1",b:"30",c:"1",d:"1"},
    //     {a:"1",b:"30",c:"1",d:"1456464"}
    // ],["a","b","c","d"],{autoSize:true})

</script>